#pragma once

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/IRReader.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetSelect.h"
#include "llvm/Instructions.h"
#include "llvm/PassManager.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Pass.h"
#include <cerrno>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <execinfo.h>
#include <vector>
#include <pthread.h>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <iostream>
#include <inttypes.h>
#include "llvm/Support/Signals.h"
#include "llvm/Support/Process.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Analysis/Verifier.h"
#include "Callable.h"

using namespace llvm;
using namespace std;

class StubGenerator {
public:
	StubGenerator(Function *F, Instruction *&InsertBefore, ExecutionEngine *EE);
	bool SliceAndCompile(vector<Instruction*> &HotLoads);
	void Kill();
	ValueToValueMapTy ReverseVMap;
	static map<Function*, StubGenerator*> ByDst;
private:
	Function* GenerateEmptySlice(Function *F);

	Function *Slice;
	LLVMContext &C;
	Function *F;
	Module *M;
	Function *Stub;
	ExecutionEngine *EE;

	GlobalVariable *Pid, *ShouldFork;
	int32_t *PidPtr, *ShouldForkPtr;
};
